/**
 * 拖拽排序数据表格组件
 */
import React, { Component ,Fragment} from 'react';
import { Table, Button, Popover } from 'antd';

import { isEmpty ,isArrayObject,doActionHandler,ajax,isNull} from '../common';

import { getUITable ,getUIList} from '../uiConfig';

import UIIcon from './UIIcon';
import UIActionBar from './UIActionBar';
import {DragDropContext, DragSource, DropTarget} from "react-dnd";
import HTML5Backend from "react-dnd-html5-backend";

function dragDirection(
    dragIndex,
    hoverIndex,
    initialClientOffset,
    clientOffset,
    sourceClientOffset,
) {
    const hoverMiddleY = (initialClientOffset.y - sourceClientOffset.y) / 2;
    const hoverClientY = clientOffset.y - sourceClientOffset.y;
    if (dragIndex < hoverIndex && hoverClientY > hoverMiddleY) {
        return 'downward';
    }
    if (dragIndex > hoverIndex && hoverClientY < hoverMiddleY) {
        return 'upward';
    }
}

class BodyRow extends React.Component {
    render() {
        const {
            isOver,
            connectDragSource,
            connectDropTarget,
            moveRow,
            dragRow,
            clientOffset,
            sourceClientOffset,
            initialClientOffset,
            ...restProps
        } = this.props;
        const style = { ...restProps.style, cursor: 'move' };

        let className = restProps.className;
        if (isOver && initialClientOffset) {
            const direction = dragDirection(
                dragRow.index,
                restProps.index,
                initialClientOffset,
                clientOffset,
                sourceClientOffset
            );
            if (direction === 'downward') {
                className += ' drop-over-downward';
            }
            if (direction === 'upward') {
                className += ' drop-over-upward';
            }
        }

        return connectDragSource(
            connectDropTarget(
                <tr
                    {...restProps}
                    className={className}
                    style={style}
                />
            )
        );
    }
}

const rowSource = {
    beginDrag(props) {
        return {
            index: props.index,
        };
    },
};

const rowTarget = {
    drop(props, monitor) {
        const dragIndex = monitor.getItem().index;
        const hoverIndex = props.index;

        // Don't replace items with themselves
        if (dragIndex === hoverIndex) {
            return;
        }

        // Time to actually perform the action
        props.moveRow(dragIndex, hoverIndex);

        // Note: we're mutating the monitor item here!
        // Generally it's better to avoid mutations,
        // but it's good here for the sake of performance
        // to avoid expensive index searches.
        monitor.getItem().index = hoverIndex;
    },
};

const DragableBodyRow = DropTarget('row', rowTarget, (connect, monitor) => ({
    connectDropTarget: connect.dropTarget(),
    isOver: monitor.isOver(),
    sourceClientOffset: monitor.getSourceClientOffset(),
}))(
    DragSource('row', rowSource, (connect, monitor) => ({
        connectDragSource: connect.dragSource(),
        dragRow: monitor.getItem(),
        clientOffset: monitor.getClientOffset(),
        initialClientOffset: monitor.getInitialClientOffset(),
    }))(BodyRow)
);

class DragSortingTable extends Component {
    constructor(props) {
        super(props);

        this.state = {
            data: [],
            selectedRowKeys: [],
            pagination: { current: 1, pageSize: 10 },
            params: {},
            loading: false,
            filteredInfo : props.filteredInfo,
            components : {
                body: {
                    row: DragableBodyRow,
                },
            },
            canDrag:this.props.canDrag !== undefined ? this.props.canDrag : false
        };
    }

    static defaultProps = {
        autoLoad:　false,
        selectMode : 'multi',
    }

    setTableConfig = (data) => {
        this.setState({
            tableConfig:data
        })
    }

    getParent = () => {
        return this.props.parent;
    }

    onSelectChange = (selectedRowKeys,selectedRows) => {
        this.setState({ selectedRowKeys });
        if (this.props.onSelectChange !== undefined) {
            this.props.onSelectChange(selectedRowKeys);
        }
    }

    getSelectedRowKeys = () => {
        return this.state.selectedRowKeys;
    }

    getListData = () => {
        return this.state.data;
    }

    setListData = (listData) => {
        this.setState({data : listData});
    }

    getSelectedDatas = () => {
        const tableConfig = getUITable(this.props.tableConfigId);
        const { data, selectedRowKeys } = this.state;
        const selectedDatas = [];

        data.forEach((rowData) => {
            if (selectedRowKeys.indexOf(rowData[tableConfig.rowId]) !== -1) {
                selectedDatas.push(rowData);
            }
        });
        return selectedDatas;
    }

    setSelectedRowKeys = (rowKeys) => {
        this.setState({ selectedRowKeys: rowKeys });
    }

    clearSelectedRowKeys = () => {
        this.setState({ selectedRowKeys: [] });
    }

    handleCellAction = (cellAction, record) => {
        const { history, actionHandler, parent } = this.props;
        const actionEvent = {
            actionId: cellAction.actionId,
            action: cellAction.handler,
            component: parent !== null ? parent : this,
            params: record
        };

        if (actionHandler) {
            if (cellAction.handler.startsWith('/') && history) {

                history.push(cellAction.handler, record);
            }
            else {
                doActionHandler(actionEvent, actionHandler(actionEvent));
            }
        }
    }

    handleTableChange = (pagination, filters, sorter) => {
        //console.log(filters);
        const pager = { ...this.state.pagination };
        pager.current = pagination.current;
        pager.pageSize = pagination.pageSize;
        this.setState({
            pagination: pager,
            filteredInfo: filters,
        });

        setTimeout(() => {
            this.loadData({
                pageSize: pagination.pageSize,
                current: pagination.current,
                sortField: sorter.field,
                sortOrder: sorter.order,
                //...this.state.params,
                //...filters,
            });
        });
    }

    loadData = (params = {}) => {
        const pagination = { ...this.state.pagination };
        this.setState({ loading: true });
        //this.setState({ selectedRowKeys: [] });
        //console.log(this.state);
        const owner = this;
        let requestParams = { ...this.state.params,...this.state.filteredInfo };
        for (let key in params) {
            if (isArrayObject(params[key])) {
                for (let i = 0; i < params[key].length; i++) {
                    requestParams[key + '[' + i + ']'] = params[key][i];
                }
            }
            else {
                requestParams[key] = params[key];
            }
        }
        //console.log(params);
        if (!params.current) {
            params.current = pagination.current;
        }
        if (!params.pageSize) {
            params.pageSize = pagination.pageSize;
        }
        requestParams.offset = (params.current - 1) * params.pageSize;
        requestParams.limit = params.pageSize;
        //console.log('requestParams:', requestParams);
        //add url params function
        requestParams = {...this.props.params,...requestParams}
        const request = ajax(this.props.dataUrl, { tableConfigId: this.props.tableConfigId, ...requestParams, });
        request.then((data) => {
            pagination.total = data.total;
            pagination.pageSize = data.pageCount;
            if (data.records.length === 0 && pagination.current > 1) {
                pagination.current = 1;
            }
            else {
                pagination.current = params.current;
            }

            owner.setState({
                loading: false,
                data: data.records,
                pagination
            });
        });
    }

    searchData = (params = {}) => {
        this.setState({ params: params });
        this.loadData({ ...params });
    }

    clearData = () => {
        this.setState({ data: [] });
    }

    enableDragTable = (canDrag) => {
        this.setState({
            canDrag:canDrag ? true : false
        })
    }

    moveRow = async (dragIndex, hoverIndex) => {
        // const { pagination } = this.state;
        let dragData = this.state.data[dragIndex];
        let hoverData = this.state.data[hoverIndex];
        // if(this.props.actionHandler !== undefined &&
        //    this.props.actionHandler().moveRow !== undefined) {
        //     this.props.actionHandler().moveRow(dragData,hoverData)
        // }
        if(this.props.onMoveRow !== undefined) {
            this.props.onMoveRow(dragData,hoverData)
        }
    };

    componentDidMount() {
        if (this.props.autoLoad) {
            const pager = { ...this.state.pagination};
            pager.current = 1;
            pager.pageSize = 10;
            this.loadData(pager);
        }
    }

    componentWillUnmount() {
    }

    render() {
        const owner = this;

        const dataSet = this.state.data;

        const filteredInfo = this.state.filteredInfo;

        const { actionHandler, history, location, actionVisibleMap, cellRender, rowActionGroupId } = this.props;

        let tableConfig = []
        if(this.state.tableConfig !== undefined) {
            tableConfig = this.state.tableConfig;
        } else {
            tableConfig = getUITable(this.props.tableConfigId);
        }

        const columns = tableConfig.columnList.map((column) => {
            const columnProp = {
                title: column.label,
                dataIndex: column.property,
                sorter: column.canSort,
                width: column.width,
                render(text, record) {

                    const cellActions = [];
                    if (column.columnDataList.length > 0) {
                        column.columnDataList.forEach((colData) => {

                            if (colData.label === "actionGroupId") {

                                cellActions.push(<UIActionBar key={column.id + 'ActionBar'} data={record}
                                    dataSet={dataSet}
                                    history={history}
                                    location={location}
                                    parent={owner}
                                    actionGroupId={colData.data}
                                    actionHandler={actionHandler}
                                    actionVisibleMap={actionVisibleMap}
                                />);
                            }
                        });
                    }

                    const cellImageList = column.imageList.map(icon => {
                        return {
                            key: icon.pattern,
                            image: icon.image
                        };
                    });

                    const cellValueList = isEmpty(column.listDataSource) ? [] : getUIList(column.listDataSource).listData.map(data => {
                        return {
                            data: data.data,
                            label: data.label
                        };
                    });

                    const CellContent = [];

                    cellImageList.forEach( (imageItem,index) =>{

                        if (imageItem.image in record === false && (text === imageItem.key || imageItem.key === '*')) {
                            CellContent.push(<UIIcon key={imageItem.image + index} icon={imageItem.image} fixedWidth></UIIcon>);
                        }
                        else if (imageItem.image in record) {
                            CellContent.push(<UIIcon key={imageItem.image + index} icon={record[imageItem.image]} fixedWidth></UIIcon>);
                        }
                        else if(text === null && imageItem.key === 'null') {
                            CellContent.push(<UIIcon key={imageItem.image + index} icon={imageItem.image} fixedWidth></UIIcon>);
                        }
                    });

                    if (cellActions.length > 0) {
                        CellContent.push(<Popover key={column.id + 'CellAction'} placement="bottom" content={cellActions} ><Button type="primary" size="small" icon="form"></Button></Popover>);
                    }

                    if (column.showValue && isEmpty(column.listDataSource) === true) {
                        CellContent.push(text);
                    }

                    if (isEmpty(column.listDataSource) === false) {
                        cellValueList.forEach( (cellValue) => {
                            if (text === cellValue.data) {
                                CellContent.push(cellValue.label);
                            }
                        });
                    }

                    if (cellRender !== undefined) {
                        cellRender(column, CellContent, record, dataSet)
                    }

                    return (
                        <Fragment>
                            {CellContent}
                        </Fragment>
                    )
                }
            };

            if (column.frozen === true) {
                columnProp.fixed = 'left';
            }

            if (column.canFilter === true && isEmpty(column.listDataSource) === false) {

                columnProp.filters = getUIList(column.listDataSource).listData.map((data) => {
                    return {
                        text: data.label,
                        value: data.data
                    }
                });

                if(isNull(filteredInfo) === false && isNull(filteredInfo[column.property]) === false){
                    //console.log(isArrayObject(filteredInfo[column.property]));
                    if(isArrayObject(filteredInfo[column.property])){
                        columnProp.filteredValue = filteredInfo[column.property];
                    }
                    else{
                        columnProp.filteredValue = [filteredInfo[column.property]];
                    }
                }
            }

            return columnProp;

        });

        const paginationProps = {
            showSizeChanger: true,
            showQuickJumper: true,
            //showTotal : true,
            ...this.state.pagination,
        };

        const { loading, selectedRowKeys } = this.state;

        const rowSelection = { selectedRowKeys };

        if (this.props.selectMode !== 'none') {
            rowSelection.onChange = this.onSelectChange;
            //rowSelection.fixed = true;
            rowSelection.type = this.props.selectMode === 'multi' ? 'checkbox' : 'radio';
        }

        if (isEmpty(rowActionGroupId) === false) {
            columns.splice(0, 0, {
                title: '操作',
                dataIndex: tableConfig.rowId,
                sorter: false,
                width: 60,
                render(text, record) {

                    const cellActions = [];
                    if (isEmpty(rowActionGroupId) === false) {
                        cellActions.push(<UIActionBar key={record[tableConfig.rowId] + 'ActionBar'} data={record}
                            dataSet={dataSet}
                            history={history}
                            location={location}
                            parent={owner}
                            actionGroupId={rowActionGroupId}
                            actionHandler={actionHandler}
                            actionVisibleMap={actionVisibleMap}
                        />);
                    }
                    return (<Popover key={record[tableConfig.rowId]} placement="bottom" content={cellActions} ><Button key={record[tableConfig.rowId]} type="primary" size="small" icon="form"></Button></Popover>);
                }
            });
        }
        const componets = this.state.canDrag ? {components: this.state.components} : {};
        return (
            <Table columns={columns}
                bordered={false}
                scroll={this.props.scroll}
                rowKey={tableConfig.rowId}
                size="middle"
                rowSelection={this.props.selectMode !== 'none' ? rowSelection : null}
                dataSource={this.state.data}
                pagination={paginationProps}
                loading={loading}
                onChange={this.handleTableChange}
                {...componets}
                onRow={(record, index) => ({
                   index,
                   moveRow: this.moveRow,
                })
                }
            />
        );
    }
}

const DragTable = DragDropContext(HTML5Backend)(DragSortingTable);

export default class UIDragDataTable extends React.Component{

    setSelectedRowKeys = (rowKeys) => {
        const { dataComponent } = this.refs;
        dataComponent.ref.current.setSelectedRowKeys(rowKeys);
    }

    clearSelectedRowKeys = () => {
        const { dataComponent } = this.refs;
        dataComponent.ref.current.clearSelectedRowKeys();
    }

    searchData = (params = {}) => {
        const { dataComponent } = this.refs;
        dataComponent.ref.current.searchData(params)
    }

    enableDragTable(canDrag) {
        const { dataComponent } = this.refs;
        dataComponent.ref.current.enableDragTable(canDrag)
    }

    render() {
        return ( <DragTable ref='dataComponent' {...this.props} /> )
    }
}
